<?php


namespace App\Service\Admin;


use App\Constants\ErrorCode;
use App\Constants\Model\UserWithdraw;
use App\Dao\CooperativeDao;
use App\Dao\UserWithdrawDao;
use App\Dao\UserWithDrawLogDao;
use App\Exception\BusinessException;
use App\Model\UserWithdrawLog;
use App\Utils\Excel;
use App\Utils\Log;
use App\Utils\Notice\Sender;
use App\Utils\Notice\UserWithdrawReject;
use App\Utils\Notice\UserWithdrawSuccess;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;

class UserWithDrawService extends BaseService
{

    /**
     * @Inject()
     * @var UserWithdrawDao
     */
    protected $userWithDrawDao;

    /**
     * @Inject()
     * @var UserWithDrawLogDao
     */
    protected $userWithDrawLogDao;

    /**
     * @Inject()
     * @var CooperativeDao
     */
    protected $cooperativeDao;

    /**
     * @param array $where
     * @return array
     */
    public function index(array $where): array
    {
        $where['is_self_merchant'] = UserWithdraw::IS_SELF_MERCHANT_NO;
        $pageInfo = $this->extractPaginateInfo($where);
        $where = $this->formatWhereRegionToCooperative($where);
        $index = $this->userWithDrawDao->where($where)->with('user')->paginate(
            $pageInfo['perPage'], ['*'], 'page', $pageInfo['page']
        );
        return $this->formatIndex($index);
    }

    public function formatIndex(\Hyperf\Contract\LengthAwarePaginatorInterface $index)
    {
        $data = [];
        /** @var \App\Model\UserWithdraw $userWithdraw */
        foreach ($index->items() as $userWithdraw) {
            $data[] = [
                'id' => $userWithdraw->id,
                'user_name' => $userWithdraw->user->nickname,
                'user_avatar' => $userWithdraw->user->avatar,
                'phone' => $userWithdraw->user->phone,
                'ali_account' => $userWithdraw->user->alipay,
                'amount' => $userWithdraw->amount,
                'message' => $userWithdraw->message,
                'created_at' => $userWithdraw->created_at->toDatetimeString()
            ];
        }
        return [
            'data' => $data,
            'current_page' => $index->currentPage(),
            'total' => $index->total(),
            'per_page' => $index->perPage()
        ];
    }

    /**
     * @param int $userWithDrawId
     * @return \App\Model\UserWithdraw
     */
    public function confirm(int $userWithDrawId): \App\Model\UserWithdraw
    {
        /** @var \App\Model\UserWithdraw $userWithDraw */
        $userWithDraw = $this->userWithDrawDao->firstOrThrow(
            ['id' => $userWithDrawId, 'status' => UserWithdraw::STATUS_PENDING]
        );
        $userWithDraw->status = UserWithdraw::STATUS_ON;
        $userWithDraw->save();
        return $userWithDraw;
    }

    /**
     * @param int $userWithDrawId
     * @param string $message
     * @return \App\Model\UserWithdraw
     */
    public function reject(int $userWithDrawId, string $message): \App\Model\UserWithdraw
    {
        /** @var \App\Model\UserWithdraw $userWithDraw */
        $userWithDraw = $this->userWithDrawDao->firstOrThrow(
            ['id' => $userWithDrawId, 'status' => UserWithdraw::STATUS_PENDING]
        );
        $userWithDraw->status = UserWithdraw::STATUS_FAIL;
        $userWithDraw->message = $message;
        $userWithDraw->save();

        //通知用户提现被驳回
        Sender::send($userWithDraw->user_id, new UserWithdrawReject());
        return $userWithDraw;
    }

    /**
     * @param int $userWithDrawId
     * @return \App\Model\UserWithdraw
     * @throws \Exception
     */
    public function transfer(int $userWithDrawId): \App\Model\UserWithdraw
    {
        /** @var \App\Model\UserWithdraw $userWithDraw */
        $userWithDraw = $this->userWithDrawDao->firstOrThrow(
            ['id' => $userWithDrawId, 'status' => UserWithdraw::STATUS_ON]
        );
        $user = $userWithDraw->user;

        Db::beginTransaction();
        try {
            $userWithDraw->status = UserWithdraw::STATUS_SUCCESS;
            $userWithDraw->save();

            //增加用户已提现金币总数
            $user->withdraw_gold = bcadd($user->withdraw_gold, $userWithDraw->gold);
            $user->save();

            //写日志
            $userWithDrawLog = new UserWithdrawLog(
                [
                    'user_id' => $userWithDraw->user_id,
                    'cooperative_id' => $userWithDraw->cooperative_id,
                    'user_with_draw_id' => $userWithDraw->id,
                    'gold' => $userWithDraw->gold,
                    'gold_type' => $userWithDraw->gold_type,
                    'is_self_merchant' => $userWithDraw->is_self_merchant,
                    'receive_account' => $userWithDraw->user->alipay
                ]
            );
            $userWithDrawLog->save();
            Db::commit();
        } catch (\Exception $exception) {
            Db::rollBack();
            Log::get()->error(
                $exception->getMessage(),
                [
                    'class:method' => __CLASS__ . ':' . __METHOD__,
                    'userWithDrawId' => $userWithDrawId
                ]
            );
            throw $exception;
        }

        //发送提现成功通知
        Sender::send($user->id, new UserWithdrawSuccess([
            'replaces' => [
                'amount' => bcdiv((string)$userWithDraw->gold, '100', 2)
            ]
        ]));

        return $userWithDraw;
    }

    public function userWithDrawLogs(array $where)
    {
        $index = $this->userWithDrawLogDao->paginate($where);
        return $index;
    }

    /**
     * 用户提现流水导出
     * @param array $data
     * @return \Psr\Http\Message\ResponseInterface
     * @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
     */
    public function userWithDrawExport(array $where)
    {
        $where = $this->formatWhereRegionToCooperative($where);

        $where['created_at_start'] = $where['date'] . ' 00:00:00';
        $where['created_at_end'] = $where['date'] . ' 23:59:59';
        unset($where['date']);

        $userWithDraw = $this->userWithDrawLogDao->where($where)->with('user')
            ->with('cooperative')->get();

        if (count($userWithDraw) == 0) {
            throw new BusinessException(ErrorCode::EXCEL_EXPORT_EMPTY);
        }

        $exportData = [];

        $head = [
            '用户',
            '手机号/账号',
            '时间',
            '提现金额',
            '合作商'
        ];

        foreach ($userWithDraw as $v) {
            /** @var \App\Model\UserWithdrawLog $value */
            $value = $v;
            array_push(
                $exportData,
                [
                    'nickname' => $value->user->nickname,
                    'phone' => $value->user->phone,
                    'created_at' => $value->created_at,
                    'price' => bcdiv($value->gold, 100, 2),
                    'cooperative' => $value->cooperative->nickname
                ]
            );
        }

        return Excel::export(
            "用户提现流水",
            $exportData,
            $head
        );
    }
}